using System.Collections.Generic;
using System.Text;
using Comdiv.Extensions;
using Comdiv.Model;
using Comdiv.Model.Interfaces;
using Comdiv.Logging;
using Comdiv.Application;
using Comdiv.Persistence;
using Comdiv.Inversion;
using Comdiv.Security.Acl;
using Comdiv.Conversations;
using Comdiv.IO;
using Comdiv.Security;
using System.Linq;

namespace Comdiv.Messaging{
    /// <summary>
    /// Message Query executor with native sql support for best performance, but not follow transaction scopes 
    /// of calling application
    /// </summary>
    public class SqlOptimizedMessageQueryExecutor : DefaultMessageQueryExecutor{


        public SqlOptimizedMessageQueryExecutor(){
            this.StoredProcedure = "comdiv.get_messages";
        }

        public string StoredProcedure { get; set; }

        public override IEnumerable<IMessage> doQuery(IMessageQuery query)
        {
            //allow to send native sql queries
            if (query.NativeQuery.hasContent())
            {
                //query must return codes or ids
                var table = GetConnection().GetTable(query.NativeQuery, null);
                var result = new List<IMessage>();
                foreach (var row in table.Rows)
                {
                    result.Add(Storage.Load(row.Values[0]));
                }
                return doFilter(query, result);
            }
            else{

                //but by default calls stored proc, which must perform all query and filtering (returns ids too)
                var parameters = new Dictionary<string, object>();
                parameters["usr"] = query.Usr;
                parameters["sender"] = query.Sender;
                parameters["target"] = query.Target;
                parameters["type"] = query.Type;
                parameters["broadcast"] = query.ShowBroadCasts;
                parameters["showinactive"] = query.ShowInactive;
                parameters["showreaded"] = query.ShowReaded;
                parameters["showarchived"] = query.ShowArchived;

                var sb = new StringBuilder();
                sb.Append("exec ");
                sb.Append(StoredProcedure);
                sb.Append(" ");
                bool first = true;
                foreach (var parameter in parameters){
                    if (!first) sb.Append(",");
                    sb.Append(parameter.Key);
                    sb.Append("=");
                    sb.Append(parameter.Key);
                    first = false;
                }
                var table = GetConnection().GetTable(sb.ToString(),parameters);
                var result = new List<IMessage>();
                foreach (var row in table.Rows){
                    result.Add(Storage.Load(row.Values[0]));
                }
                return result;

            }

        }
        
    }
}